﻿
#region Using Directives.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Text;
using IdSharp.AudioInfo.Inspection;
using TagLib;
using TagLib.Id3v2;
using File = TagLib.File;
using IdSharp.AudioInfo;

#endregion

namespace GDFlacTool.Common
{
    [Serializable]
    public class TrackMp3 : Track
    {
        #region Fields.

        private File _taglibfile;
        private TagLib.Id3v2.Tag _tagid3V2;
        private TagLib.Id3v1.Tag _tagid3V1;
        private IAudioFile _audioFile;
        private Mpeg _mpeg;
        private DescriptiveLameTagReader _descriptiveLameTagReader;
        private readonly bool _isEmpty;
        private readonly string _trackFormat = string.Empty;
        private readonly bool _isSupportedFormat;
        private string _id3V1Album = string.Empty;
        private string _id3V1Artist = string.Empty;
        private string _id3V1Title = string.Empty;
        private string _id3V1Year = string.Empty;
        private string _id3V1Comment = string.Empty;
        private string _id3V1Genre = string.Empty;
        private string _id3V1Track = string.Empty;
        private Id3Actions _id3Actions;

        #endregion

        #region Constructors.

        public TrackMp3() { }

        public TrackMp3(string path, Id3Actions id3Actions)
        {
            FullPath = path;

            _trackFormat = "mp3";

            _isSupportedFormat = true;

            _id3Actions = id3Actions;

            if (CreateTagLibFile(FullPath) && CreateMp3File(FullPath))
            {
                ReadFileInfo();

                ReadId3V2Tags();

                ReadId3V1Tags();

                _isEmpty = false;
            }
            else
            {
                FullPath = string.Empty;

                _isEmpty = true;
            }

            if (!string.IsNullOrEmpty(FullPath))
            {
                //CreateMp3File(FullPath);
            }
        }

        #endregion

        #region Public Methods.

        public void RemoveTag(string tag)
        {
            Frame frame = GetTagFrame(ConverFlacTypesToMp3Types(tag), tag);

            if(frame != null)
            {
                 _tagid3V2.RemoveFrame(frame);
            }
           
        }

        public void ClearTrack()
        {
            _tagid3V2.Clear();

            ReadId3V2Tags();
        }

        #endregion

        #region Override Methods.

        public override void ClearTags()
        {
            _tagid3V2.Clear();
            _tagid3V1.Clear();

            //Clear the artist tag
            Artist = string.Empty;

            //Clear the album artist tag
            Albumartist = string.Empty;

            //Clear the album tag
            Album = string.Empty;

            //Clear the title tag
            Title = string.Empty;

            //Clear year tag
            Year = string.Empty;

            //Clear the genre tag;
            Genre = string.Empty;

            //Clear the comment tag
            Comment = string.Empty;

            //Clear the comment tag
            Catalog = string.Empty;

            //Clear the track number tag
            TrackNumber = string.Empty;

            //Clear the disc number tag
            DiscNumber = string.Empty;

            //Clear the isrc number tag
            Isrc = string.Empty;

            //Clear the release type tag
            ReleaseType = string.Empty;

            //Clear the composer tag
            Composer = string.Empty;

            //Clear the original artist tag
            Originalartist = string.Empty;

            //Clear the copyright tag
            Copyright = string.Empty;

            //Clear the url tag
            Url = string.Empty;

            //Clear the copyright tag
            EncodedBy = string.Empty;

            //Clear the mood tag
            Mood = string.Empty;

            //Clear the rating tag
            Rating = string.Empty;

            //Clear the quality tag
            Quality = string.Empty;

            //Clear the bpm tag
            Bpm = string.Empty;

            //Clear the lyrics tag
            Lyrics = string.Empty;

            //Clear the compilation tag
            Compilation = false;

            //Clear the lyricist tag
            Lyricist = string.Empty;

            //Clear the original lyricist tag
            OriginalLyricist = string.Empty;

            //Clear the radio station name tag
            RadioStationName = string.Empty;

            //Clear the label tag
            Label = string.Empty;

            //Clear the conductor tag
            Conductor = string.Empty;

            //Clear the remixed by tag
            RemixedBy = string.Empty;

            //Clear the audio file url tag
            AudioFileUrl = string.Empty;

            //Clear the audio source url tag
            AudioSourceUrl = string.Empty;

            //Clear the author url tag
            AuthorUrl = string.Empty;

            //Clear the buy cd url tag
            BuyCdUrl = string.Empty;

            //Clear the radio station url tag
            RadioStationUrl = string.Empty;

            //Clear front cover art
            RemoveFrontCoverArt();

            _taglibfile.Save();
        }

        public override void SetTags(Id3Actions id3Actions)
        {
            switch (id3Actions)
            {
                case Id3Actions.WriteId3V1AndId3V2:
                    SetId3V2Tags();
                    SetId3V1Tags();
                    break;
                case Id3Actions.WriteOnlyId3V2:
                    SetId3V2Tags();
                    break;
                case Id3Actions.WriteOnlyId3V1:
                    SetId3V1Tags();
                    break;
                case Id3Actions.WriteId3V2AndDeleteId3V1:
                    SetId3V2Tags();
                    RemoveId3V1Tags();
                    break;
            }

            _taglibfile.Save();
        }

        public override bool IsTagCorrupt(out string message)
        {
            if (_taglibfile.PossiblyCorrupt)
            {
                IEnumerable<string> tmp = _taglibfile.CorruptionReasons;
                var sb = new StringBuilder();

                foreach (var line in tmp)
                {
                    sb.AppendLine(line);
                }

                message = sb.ToString();
                return true;
            }

            message = string.Empty;
            return false;
        }

        public override bool IsEmpty
        {
            get { return _isEmpty; }
        }

        public override string TrackFormat
        {
            get { return _trackFormat; }
        }

        public override bool IsSupportedTag
        {
            get { return _isSupportedFormat; }
        }

        public override void CopyTag(string tagtype, string value, string toPropertyName)
        {
            SetPropValue(toPropertyName, value);

            string id3TagType = ConverFlacTypesToMp3Types(tagtype);

            SetTagField(id3TagType, tagtype, new[] { (string)GetPropValue(toPropertyName) });

            _taglibfile.Save();
        }

        public override void SwapTag(string tagtypeFrom, string valueFrom, string propertyNameFrom, string tagtypeTo, string valueTo, string propertyNameTo)
        {
            SetPropValue(propertyNameFrom, valueTo);
            SetPropValue(propertyNameTo, valueFrom);

            //_xiphComment.SetField(tagtypeFrom, new[] { (string)GetPropValue(propertyNameFrom) });
            string id3TagTypeFrom = ConverFlacTypesToMp3Types(tagtypeFrom);
            SetTagField(id3TagTypeFrom, tagtypeFrom, new[] { (string)GetPropValue(propertyNameFrom) });
            
            //_xiphComment.SetField(tagtypeTo, new[] { (string)GetPropValue(propertyNameTo) });
            string id3TagTypeTo = ConverFlacTypesToMp3Types(tagtypeTo);
            SetTagField(id3TagTypeTo, tagtypeTo, new[] { (string)GetPropValue(propertyNameTo) });
        }

        public override string GetTag(string tagtype)
        {
            string id3TagType = ConverFlacTypesToMp3Types(tagtype);

            string value = GetTagField(id3TagType, tagtype); //_xiphComment.GetFirstField(tagtype);

            if (value != null)
            {
                return value;
            }
            return string.Empty;
        }

        public override void SetTag(string tagtype)
        {
            string id3TagType = ConverFlacTypesToMp3Types(tagtype);

            switch (tagtype)
            {
                
                case "TRACKNUMBER":
                    SetTagField(id3TagType, "TRACKNUMBER", new[] { TrackNumber });
                    _taglibfile.Save();
                    break;
                case "DISCNUMBER":
                    SetTagField(id3TagType, "DISCNUMBER", new[] {DiscNumber} );
                    _taglibfile.Save();
                    break;
                case "TITLE":
                    SetTagField(id3TagType, "TITLE", new[] { Title });
                    _taglibfile.Save();
                    break;
                case "ARTIST":
                    SetTagField(id3TagType, "ARTIST", new[] { Artist });
                    _taglibfile.Save();
                    break;
                case "ALBUMARTIST":
                    SetTagField(id3TagType, "ALBUMARTIST", new[] { Albumartist });
                    _taglibfile.Save();
                    break;
                case "ALBUM":
                    SetTagField(id3TagType, "ALBUM", new[] { Album });
                    _taglibfile.Save();
                    break;

            }
        }

        public override void SetTag(params string[] tagtype)
        {
            foreach (string s in tagtype)
            {
                SetTag(s);
            }
        }

        public override void SaveFrontCoverArt(byte[] bytes)
        {
            MemoryStream ms = null;

            try
            {
                ms = new MemoryStream(bytes);

                var picture = new Picture();

                picture.Type = PictureType.FrontCover;
                picture.MimeType = "image/jpeg";
                picture.Description = "Front Cover";
                picture.Data = ByteVector.FromStream(ms);

                _taglibfile.Tag.Pictures = new IPicture[] { picture };

                base.ArtSize = _taglibfile.Tag.Pictures[0].Data.Data.Length;

                _taglibfile.Save();
            }
            catch (Exception ex)
            {
                throw new SaveArtException(ex.Message, "Failed to save the cover art to the file");
            }
            finally
            {
                if (ms != null) ms.Close();
            }

            ReadFrontCoverArt();
        }

        public override void RemoveFrontCoverArt()
        {
            foreach (IPicture picture in _taglibfile.Tag.Pictures)
            {
                if (picture.Type == PictureType.FrontCover)
                {
                    picture.Type = PictureType.Other;
                    picture.Data.Clear();
                }
            }

            _taglibfile.Save();

            ArtImage = null;
            ArtByteArray = null;
            ArtSize = 0;
        }

        public override void ClearUndo()
        {
            if (IsTrackRenamed)
            {
                Trackrename = null;
            }
        }

        public override bool RenameTrack(MaskHelperCollection masks, TrackRename trackRename)
        {
            string newFileName = masks.Mask;
            int counter = 1;
            Trackrename = trackRename;

            foreach (MaskHelper mask in masks)
            {
                if (newFileName.Contains(mask.Mask))
                {
                    if (mask.IsStandardTag)
                    {
                        string replace = ReplaceStandardTags(mask.TagType);

                        if (replace != null)
                        {
                            newFileName = newFileName.Replace(mask.Mask, replace);
                        }
                    }
                    else
                    {
                        string replace = ReplaceNonStandardTags(mask.TagType, counter);

                        newFileName = newFileName.Replace(mask.Mask, replace);
                    }
                }

                counter++;
            }

            string temp = newFileName.Replace(Path.AltDirectorySeparatorChar, ' ');

            if (string.IsNullOrEmpty(newFileName))
            {
                return false;
            }

            temp = Functions.RemoveIllegalCharsFileName(temp);

            string tempPath = Path.GetDirectoryName(temp);

            string newPath = string.Empty;

            if (!string.IsNullOrEmpty(tempPath))
            {
                newPath = Path.GetDirectoryName(newFileName);

                if (!Path.IsPathRooted(newPath))
                {
                    if (newPath != null) newPath = newPath.Replace(":", "_");
                }
                else
                {
                    if (newPath != null)
                    {
                        string tmp = newPath.Substring(0, 2);
                        newPath = newPath.Remove(0, 2);
                        newPath = newPath.Replace(":", "_");

                        newPath = tmp + newPath;
                    }
                }
            }

            Trackrename.RenamedPath = newPath;

            Trackrename.RenamedFileName = newFileName;

            return true;
        }

        #endregion

        #region Rename From Mask Methods.

        public override void UpdateAfterRename()
        {
            if (_taglibfile.Name != FullPath)
            {
                CreateTagLibFile(FullPath);
            }

            ReadFileInfo();
            ReadId3V2Tags();
        }

        private string ReplaceNonStandardTags(MaskType type, int fileNumber)
        {
            string result;

            switch (type)
            {
                case MaskType.ENCODER:
                    result = string.Empty; //_xiphComment.VendorId;
                    break;
                case MaskType.BITRATE:
                    result = _taglibfile.Properties.AudioBitrate.ToString(CultureInfo.InvariantCulture);
                    break;
                case MaskType.PLAYTIME:
                    result = string.Format("({0:mm}:{1:ss})", _taglibfile.Properties.Duration, _taglibfile.Properties.Duration);
                    break;
                case MaskType.FILENUMBER:
                    result = fileNumber.ToString(CultureInfo.InvariantCulture);
                    break;
                case MaskType.FILENAME:
                    result = FileName;
                    break;
                case MaskType.BPM:
                    result = _taglibfile.Properties.AudioSampleRate.ToString(CultureInfo.InvariantCulture);
                    break;
                default:
                    result = string.Empty;
                    break;
            }

            if (result == null)
            {
                result = string.Empty;
            }

            return result;
        }

        private string ReplaceStandardTags(MaskType type)
        {
            string result;
            string id3TagType;

            if (type == MaskType.DATE)
            {
                id3TagType = ConverFlacTypesToMp3Types(TagType.Year);
                //result = _xiphComment.GetFirstField(TagType.Year);
                result = GetTagField(id3TagType, TagType.Year);


                if (result == null)
                {
                    return string.Empty;
                }

                if (result == string.Empty)
                {
                    string temp = ConverFlacTypesToMp3Types(TagType.Releaseyear);
                    //result = _xiphComment.GetFirstField(TagType.Releaseyear);
                    result = GetTagField(temp, TagType.Releaseyear);
                }

                return result;
            }

            if (type == MaskType.TRACKNUMBERZERO || type == MaskType.TRACKNUMBER)
            {
                id3TagType = ConverFlacTypesToMp3Types(TagType.Tracknumber);

                string temp = GetTagField(id3TagType, TagType.Tracknumber); //_xiphComment.GetFirstField(TagType.Tracknumber);

                if (temp == null)
                {
                    return string.Empty;
                }

                if (temp.Contains("/"))
                {
                    result = temp.Remove(temp.IndexOf("/", StringComparison.Ordinal));
                }
                else
                {
                    result = temp;
                }

                int number;

                if (int.TryParse(result, out number))
                {
                    if (type == MaskType.TRACKNUMBER)
                    {
                        result = string.Format("{0:#}", number);
                    }
                    else
                    {
                        result = string.Format("{0:0#}", number);
                    }
                }

                return result;
            }

            if (type == MaskType.DISCNUMBER || type == MaskType.DISCNUMBERZERO)
            {
                id3TagType = ConverFlacTypesToMp3Types(TagType.Discnumber);
                //string temp = _xiphComment.GetFirstField(TagType.Discnumber);
                string temp = GetTagField(id3TagType, TagType.Discnumber);

                if (temp == null)
                {
                    return string.Empty;
                }

                if (temp.Contains("/"))
                {
                    result = temp.Remove(temp.IndexOf("/", StringComparison.Ordinal));
                }
                else
                {
                    result = temp;
                }

                int number;

                if (int.TryParse(result, out number))
                {
                    if (type == MaskType.DISCNUMBER)
                    {
                        result = string.Format("{0:#}", number);
                    }
                    else
                    {
                        result = string.Format("{0:0#}", number);
                    }
                }

                return result;
            }

            id3TagType = ConverFlacTypesToMp3Types(type.ToString());

            result = GetTagField(id3TagType, type.ToString());//_xiphComment.GetFirstField(type.ToString());

            if (result == null)
            {
                result = string.Empty;
            }

            return result;
        }

        #endregion

        #region ID3v1 Tag Methods.

        private void ReadId3V1Tags()
        {
            if (!string.IsNullOrEmpty(_tagid3V1.Album))
            {
                _id3V1Album = _tagid3V1.Album;
            }

            if (_tagid3V1.Performers.Length > 0)
            {
                if (!string.IsNullOrEmpty(_tagid3V1.Performers[0]))
                {
                    _id3V1Artist = _tagid3V1.Performers[0];
                }
            }

            if (_tagid3V1.Performers.Length > 0 && string.IsNullOrEmpty(_id3V1Artist))
            {
                if (!string.IsNullOrEmpty(_tagid3V1.Artists[0]))
                {
                    _id3V1Artist = _tagid3V1.Artists[0];
                }
            }

            if (!string.IsNullOrEmpty(_tagid3V1.Title))
            {
                _id3V1Title = _tagid3V1.Title;
            }

            if (_tagid3V1.Year > 1900)
            {
                _id3V1Year = _tagid3V1.Year.ToString(CultureInfo.InvariantCulture);
            }

            if (!string.IsNullOrEmpty(_tagid3V1.Comment))
            {
                _id3V1Comment = _tagid3V1.Comment;
            }

            if (_tagid3V1.Genres.Length > 0)
            {
                if (!string.IsNullOrEmpty(_tagid3V1.Genres[0]))
                {
                    _id3V1Genre = _tagid3V1.Genres[0];
                }
            }

            if (_tagid3V1.Track > 0)
            {
                _id3V1Track = _tagid3V1.Track.ToString(CultureInfo.InvariantCulture);
            }
        }

        private void TransferId3V1ToId3V2()
        {
            if (string.IsNullOrEmpty(Album) && !string.IsNullOrEmpty(_id3V1Album))
            {
                Album = _id3V1Album;
            }

            if (string.IsNullOrEmpty(Artist) && !string.IsNullOrEmpty(_id3V1Artist))
            {
                Artist = _id3V1Artist;
            }

            if (string.IsNullOrEmpty(Title) && !string.IsNullOrEmpty(_id3V1Title))
            {
                Title = _id3V1Title;
            }

            if (string.IsNullOrEmpty(Year) && !string.IsNullOrEmpty(_id3V1Year))
            {
                Year = _id3V1Year;
            }

            if (string.IsNullOrEmpty(Comment) && !string.IsNullOrEmpty(_id3V1Comment))
            {
                Comment = _id3V1Comment;
            }

            if (string.IsNullOrEmpty(Genre) && !string.IsNullOrEmpty(_id3V1Genre))
            {
                Genre = _id3V1Genre;
            }

            if (string.IsNullOrEmpty(TrackNumber) && !string.IsNullOrEmpty(_id3V1Track))
            {
                TrackNumber = _id3V1Track;
            }
        }

        private void RemoveId3V1Tags()
        {
            _tagid3V1.Clear();
        }

        private void SetId3V1Tags()
        {
            if (!string.IsNullOrEmpty(Album))
            {
                _tagid3V1.Album = Album;
            }

            if (!string.IsNullOrEmpty(Artist))
            {
                if (_tagid3V1.Performers.Length > 0)
                {
                    _tagid3V1.Performers[0] = Artist;
                }
                else
                {
                    _tagid3V1.Performers = new []{Artist};
                }

                if (_tagid3V1.Artists.Length > 0)
                {
                    _tagid3V1.Artists[0] = Artist;
                }
                else
                {
                    _tagid3V1.Artists = new []{Artist};
                }
            }

            if (!string.IsNullOrEmpty(Title))
            {
                _tagid3V1.Title = Title;
            }

            if (!string.IsNullOrEmpty(Year) && Functions.IsNumeric(Year) && Year.Length == 4)
            {
                _tagid3V1.Year = uint.Parse(Year);
            }
            else
            {
                DateTime dt;

                if (DateTime.TryParse(Year, out dt))
                {
                    _tagid3V1.Year = uint.Parse(dt.Year.ToString(CultureInfo.InvariantCulture));
                }
            }

            if (!string.IsNullOrEmpty(Comment))
            {
                _tagid3V1.Comment = Comment;
            }

            if (!string.IsNullOrEmpty(Genre))
            {
                if (_tagid3V1.Genres.Length > 0)
                {
                    _tagid3V1.Genres[0] = Genre;
                }
                else
                {
                    _tagid3V1.Genres = new []{Genre};
                }
            }

            if (!string.IsNullOrEmpty(TrackNumber))
            {
                var splitter = new[] { '/' };

                string[] split = TrackNumber.Split(splitter, StringSplitOptions.RemoveEmptyEntries);

                if (split.Length > 0 && Functions.IsNumeric(split[0]))
                {
                    _tagid3V1.Track = uint.Parse(split[0]);
                }
            }
        }

        #endregion

        #region ID3v2 Tag Methods.

        private void ReadId3V2Tags()
        {
            var frames = _tagid3V2.GetFrames();

            List<Frame> frameList = frames.ToList();

            foreach (var frame in frameList)
            {
                switch (frame.FrameId.ToString())
                {
                    case "TSSE": //Read the encoder tag
                        string encoder = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Encoder = !string.IsNullOrEmpty(encoder) ? encoder : string.Empty;
                        break;
                    case "TPE1": //Read the artist tag
                        string artist = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Artist = !string.IsNullOrEmpty(artist) ? artist : string.Empty;
                        break;
                    case "TPE2": //Read the album artist tag
                        string albumartist = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Albumartist = !string.IsNullOrEmpty(albumartist) ? albumartist : string.Empty;
                        break;
                    case "TALB": //Read the album tag
                        string album = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Album = !string.IsNullOrEmpty(album) ? album : string.Empty;
                        break;
                    case "TIT2": //Read the title tag
                        string title = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Title = !string.IsNullOrEmpty(title) ? title : string.Empty;
                        break;
                    case "TYER": //Read the year tag
                        string year = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Year = !string.IsNullOrEmpty(year) ? year : string.Empty;
                        break;
                    case "TDRC": //Read the recording year tag
                        string recordingYear = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        if (!string.IsNullOrEmpty(recordingYear) && string.IsNullOrEmpty(Year))
                        {
                            Year = recordingYear;
                        }
                        break;
                    case "TDRL": //Read the release year tag
                        string releaseYear = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        if (!string.IsNullOrEmpty(releaseYear) && string.IsNullOrEmpty(Year))
                        {
                            Year = releaseYear;
                        }
                        break;
                    case "TCON": //Read the genre tag
                        string genre = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Genre = !string.IsNullOrEmpty(genre) ? genre : string.Empty;
                        break;
                    case "TRSN":
                        string radiostationname = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        RadioStationName = !string.IsNullOrEmpty(radiostationname) ? radiostationname : string.Empty;
                        break;
                    case "TPUB":
                        string label = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Label = !string.IsNullOrEmpty(label) ? label : string.Empty;
                        break;
                    case "TPE3":
                        string conductor = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Conductor = !string.IsNullOrEmpty(conductor) ? conductor : string.Empty;
                        break;
                    case "TPE4":
                        string remixedby = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        RemixedBy = !string.IsNullOrEmpty(remixedby) ? remixedby : string.Empty;
                        break;
                    case "TRCK": //Read the track number tag
                        string tracknumber = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        TrackNumber = !string.IsNullOrEmpty(tracknumber) ? tracknumber : string.Empty;
                        break;
                    case "TPOS": //Read the disc number tag
                        string discnumber = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        DiscNumber = !string.IsNullOrEmpty(discnumber) ? discnumber : string.Empty;
                        break;
                    case "TSRC": //Read the isrc tag
                        string isrc = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Isrc = !string.IsNullOrEmpty(isrc) ? isrc : string.Empty;
                        break;
                    case "TCOM": //Read the composer tag
                        string composer = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Composer = !string.IsNullOrEmpty(composer) ? composer : string.Empty;
                        break;
                    case "TOPE": //Read the original artist tag
                        string originalartist = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Originalartist = !string.IsNullOrEmpty(originalartist) ? originalartist : string.Empty;
                        break;
                    case "TCOP": //Read the copyright tag
                        string copyright = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Copyright = !string.IsNullOrEmpty(copyright) ? copyright : string.Empty;
                        break;
                    case "TENC":
                        string encodedby = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        EncodedBy = !string.IsNullOrEmpty(encodedby) ? encodedby : string.Empty;
                        break;
                    case "TBPM":
                        string bpm = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Bpm = !string.IsNullOrEmpty(bpm) ? bpm : string.Empty;
                        break;
                    case "TEXT":
                        string lyricist = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Lyricist = !string.IsNullOrEmpty(lyricist) ? lyricist : string.Empty;
                        break;
                    case "TOLY":
                        string originallyricist = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        OriginalLyricist = !string.IsNullOrEmpty(originallyricist) ? originallyricist : string.Empty;
                        break;
                    case "TMOO":
                        string mood1 = ReadTagArrayValue(((TextInformationFrame)frame).Text);
                        Mood = !string.IsNullOrEmpty(mood1) ? mood1 : string.Empty;
                        break;
                    case "TXXX":
                        if (((UserTextInformationFrame)frame).Description == "ReleaseType")
                        {
                            string h2Releasetype = ReadTagArrayValue(((UserTextInformationFrame)frame).Text);
                            ReleaseType = !string.IsNullOrEmpty(h2Releasetype) ? h2Releasetype : string.Empty;
                        }
                        else if (((UserTextInformationFrame)frame).Description == "Comment")
                        {
                            string h2Comment = ReadTagArrayValue(((UserTextInformationFrame)frame).Text);
                            Comment = !string.IsNullOrEmpty(h2Comment) ? h2Comment : string.Empty;
                        }
                        else if (((UserTextInformationFrame)frame).Description == "AlbumArtist")
                        {
                            string h2AlbumArtist = ReadTagArrayValue(((UserTextInformationFrame)frame).Text);
                            Albumartist = !string.IsNullOrEmpty(h2AlbumArtist) ? h2AlbumArtist : string.Empty;
                        }
                        break;
                    case "COMM":
                        if (((CommentsFrame)frame).Description == string.Empty)
                        {
                            string comment = ((CommentsFrame)frame).Text;
                            Comment = !string.IsNullOrEmpty(comment) ? comment : string.Empty;
                        }
                        else if (((CommentsFrame)frame).Description == "Catalog Number")
                        {
                            string catalogNumber = ((CommentsFrame)frame).Text;
                            Catalog = !string.IsNullOrEmpty(catalogNumber) ? catalogNumber : string.Empty;
                        }
                        else if (((CommentsFrame)frame).Description == "LABELNO")
                        {
                            string labelNo = ((CommentsFrame)frame).Text;
                            Catalog = !string.IsNullOrEmpty(labelNo) ? labelNo : string.Empty;
                        }
                        else if (((CommentsFrame)frame).Description == "MusicMatch_Mood")
                        {
                            if (string.IsNullOrEmpty(Mood))
                            {
                                string mood = ((CommentsFrame)frame).Text;
                                Mood = !string.IsNullOrEmpty(mood) ? mood : string.Empty;
                            }
                        }
                        else if (((CommentsFrame)frame).Description == "Songs-DB_Preference")
                        {
                            string quality = ((CommentsFrame)frame).Text;
                            Quality = !string.IsNullOrEmpty(quality) ? quality : string.Empty;
                        }
                        break;
                    case "POPM":
                        string rating = ((PopularimeterFrame)frame).Rating.ToString(CultureInfo.InvariantCulture);
                        Rating = !string.IsNullOrEmpty(rating) ? rating : string.Empty;
                        break;
                    case "USLT":
                        string lyrics = ((UnsynchronisedLyricsFrame)frame).Text;
                        Lyrics = !string.IsNullOrEmpty(lyrics) ? lyrics : string.Empty;
                        break;
                    case "WXXX": //Read the url tag
                        byte[] bv = ((UnknownFrame)frame).Data.Data;
                        string url = GetStringFromByteArray(bv);
                        Url = !string.IsNullOrEmpty(url) ? url : string.Empty;
                        break;
                    case "WOAF":
                        string audiofileurl = ((UnknownFrame)frame).Data.ToString();
                        AudioFileUrl = !string.IsNullOrEmpty(audiofileurl) ? audiofileurl : string.Empty;
                        break;
                    case "WOAS":
                        string audiosourceurl = ((UnknownFrame)frame).Data.ToString();
                        AudioSourceUrl = !string.IsNullOrEmpty(audiosourceurl) ? audiosourceurl : string.Empty;
                        break;
                    case "WOAR":
                        string authorurl = ((UnknownFrame)frame).Data.ToString();
                        AuthorUrl = !string.IsNullOrEmpty(authorurl) ? authorurl : string.Empty;
                        break;
                    case "WCOM":
                        string buycdurl = ((UnknownFrame)frame).Data.ToString();
                        BuyCdUrl = !string.IsNullOrEmpty(buycdurl) ? buycdurl : string.Empty;
                        break;
                    case "WORS":
                        string radiostationurl = ((UnknownFrame)frame).Data.ToString();
                        RadioStationUrl = !string.IsNullOrEmpty(radiostationurl) ? radiostationurl : string.Empty;
                        break;
                }
            }

            Compilation = _tagid3V2.IsCompilation;

            TransferId3V1ToId3V2();

            //Read fron cover art
            ReadFrontCoverArt();
        }

        private void SetId3V2Tags()
        {
            string id3TagType;
            //Set the title tag
            if (IsTitleChanged)
            {
                //_xiphComment.SetField(TagType.Title, new[] { Title });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Title);
                SetTagField(id3TagType, TagType.Title, new[] { Title });
                IsTitleChanged = false;
            }

            //Set the artist tag
            if (IsArtistChanged)
            {
                //_xiphComment.SetField(TagType.Artist, new[] { Artist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Artist);
                SetTagField(id3TagType, TagType.Artist, new[] { Artist });
                IsArtistChanged = false;
            }

            //Set the album tag
            if (IsAlbumChanged)
            {
                //_xiphComment.SetField(TagType.Album, new[] { Album });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Album);
                SetTagField(id3TagType, TagType.Album, new[] { Album });
                IsAlbumChanged = false;
            }

            //Set the album artist tag
            if (IsAlbumArtistChanged)
            {
                //_xiphComment.SetField(TagType.Albumartist, new[] { Albumartist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Albumartist);
                SetTagField(id3TagType, TagType.Albumartist, new[] { Albumartist });

                //_xiphComment.SetField(TagType.AlbumArtist, new[] { Albumartist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.AlbumArtist);
                SetTagField(id3TagType, TagType.AlbumArtist, new[] { Albumartist });

                //_xiphComment.SetField(TagType.H2AlbumArtist, new[] { Albumartist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.H2AlbumArtist);
                SetTagField(id3TagType, TagType.H2AlbumArtist, new[] { Albumartist });
                IsAlbumChanged = false;
            }

            //Set the year tag
            if (IsYearChanged)
            {
                //_xiphComment.SetField(TagType.Year, new[] { Year });
                //id3TagType = ConverFlacTypesToMp3Types(TagType.Year);
                //SetTagField(id3TagType, TagType.Year, new[] { Year });

                //_xiphComment.SetField(TagType.Releaseyear, new[] { Year });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Releaseyear);
                SetTagField(id3TagType, TagType.Releaseyear, new[] { Year });

                //_xiphComment.SetField(TagType.H2Releaseyear, new[] { Year });
                id3TagType = ConverFlacTypesToMp3Types(TagType.H2Releaseyear);
                SetTagField(id3TagType, TagType.H2Releaseyear, new[] { Year });
                IsYearChanged = false;
            }

            //Set the genre tag
            if (IsGenreChanged)
            {
                //_xiphComment.SetField(TagType.Genre, new[] { Genre });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Genre);
                SetTagField(id3TagType, TagType.Genre, new[] { Genre });
                IsGenreChanged = false;
            }

            //Set the comment tag
            if (IsCommentChanged)
            {
                //_xiphComment.SetField(TagType.Comment, new[] { Comment });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Comment);
                SetTagField(id3TagType, TagType.Comment, new[] { Comment });

                id3TagType = ConverFlacTypesToMp3Types("H2_COMMENT");
                SetTagField(id3TagType, "H2_COMMENT", new[] { Comment });
                IsCommentChanged = false;
            }

            //Set the SHN ID tag
            if (IsCatalogChanged)
            {
                //_xiphComment.SetField(TagType.LabelNo, new[] { Catalog });
                id3TagType = ConverFlacTypesToMp3Types(TagType.LabelNo);
                SetTagField(id3TagType, TagType.LabelNo, new[] { Catalog });

                //_xiphComment.SetField(TagType.CatalogNumber, new[] { Catalog });
                id3TagType = ConverFlacTypesToMp3Types(TagType.CatalogNumber);
                SetTagField(id3TagType, TagType.CatalogNumber, new[] { Catalog });
                IsCatalogChanged = false;
            }

            //Set the track number tag
            if (IsTrackNumberChanged)
            {
                //_xiphComment.SetField(TagType.Tracknumber, new[] { TrackNumber });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Tracknumber);
                SetTagField(id3TagType, TagType.Tracknumber, new[] { TrackNumber });
                IsTrackNumberChanged = false;
            }

            //Set the disc number tag
            if (IsDiscNumberChanged)
            {
                //_xiphComment.SetField(TagType.Discnumber, new[] { DiscNumber });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Discnumber);
                SetTagField(id3TagType, TagType.Discnumber, new[] { DiscNumber });
                IsDiscNumberChanged = false;
            }

            //Set the isrc number tag
            if (IsIsrcChanged)
            {
                //_xiphComment.SetField(TagType.Isrc, new[] { Isrc });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Isrc);
                SetTagField(id3TagType, TagType.Isrc, new[] { Isrc });
                IsIsrcChanged = false;
            }

            //Set the release type tag
            if (IsReleaseTypeChanged)
            {
                //_xiphComment.SetField(TagType.ReleaseType, new[] { ReleaseType });
                id3TagType = ConverFlacTypesToMp3Types(TagType.ReleaseType);
                SetTagField(id3TagType, TagType.ReleaseType, new[] { ReleaseType });
                IsReleaseTypeChanged = false;
            }

            //Set the composer tag
            if (IsComposerChanged)
            {
                //_xiphComment.SetField(TagType.Composer, new[] { Composer });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Composer);
                SetTagField(id3TagType, TagType.Composer, new[] { Composer });
                IsComposerChanged = false;
            }

            //Set the original artist tag
            if (IsOriginalArtistChanged)
            {
                //_xiphComment.SetField(TagType.OriginalArtist, new[] { Originalartist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.OriginalArtist);
                SetTagField(id3TagType, TagType.OriginalArtist, new[] { Originalartist });
                IsOriginalArtistChanged = false;
            }

            //Set the copyright tag
            if (IsCopyrightChanged)
            {
                //_xiphComment.SetField(TagType.Copyright, new[] { Copyright });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Copyright);
                SetTagField(id3TagType, TagType.Copyright, new[] { Copyright });
                IsCopyrightChanged = false;
            }

            //Set the url tag
            if (IsUrlChanged)
            {
                //_xiphComment.SetField(TagType.Url, new[] { Url });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Url);
                SetTagField(id3TagType, TagType.Url, new[] { Url });
                IsUrlChanged = false;
            }

            //Set the encoded by tag
            if (IsEncodedByChanged)
            {
                //_xiphComment.SetField(TagType.EncodedBy, new[] { EncodedBy });
                id3TagType = ConverFlacTypesToMp3Types(TagType.EncodedBy);
                SetTagField(id3TagType, TagType.EncodedBy, new[] { EncodedBy });
                IsEncodedByChanged = false;
            }

            //Set the mood by tag
            if (IsMoodChanged)
            {
                //_xiphComment.SetField(TagType.Mood, new[] { Mood });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Mood);
                SetTagField(id3TagType, TagType.Mood, new[] { Mood });
                IsMoodChanged = false;
            }

            //Set the rating by tag
            if (IsRatingChanged)
            {
                if (Rating != "0")
                {
                    //_xiphComment.SetField(TagType.Rating, new[] { Rating });
                    id3TagType = ConverFlacTypesToMp3Types(TagType.Rating);
                    SetTagField(id3TagType, TagType.Rating, new[] { Rating });
                }
                else
                {
                    RemoveTag(TagType.Rating);
                }

                IsRatingChanged = false;
            }

            //Set the quality by tag
            if (IsQualityChanged)
            {
                //_xiphComment.SetField(TagType.Quality, new[] { Quality });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Quality);
                SetTagField(id3TagType, TagType.Quality, new[] { Quality });
                IsQualityChanged = false;
            }

            //Set the bpm by tag
            if (IsBpmChanged)
            {
                //_xiphComment.SetField(TagType.Bpm, new[] { Bpm });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Bpm);
                SetTagField(id3TagType, TagType.Bpm, new[] { Bpm });
                IsBpmChanged = false;
            }

            //Set the compilation tag
            if (IsCompilationChanged)
            {
                //_xiphComment.IsCompilation = Compilation;
                _tagid3V2.IsCompilation = Compilation;
                IsCompilationChanged = false;
            }

            //Set the lyrics tag
            if (IsLyricsChanged)
            {
                if (!string.IsNullOrEmpty(Lyrics))
                {
                    //_xiphComment.SetField(TagType.Lyrics, new[] { Lyrics });
                    id3TagType = ConverFlacTypesToMp3Types(TagType.Lyrics);
                    SetTagField(id3TagType, TagType.Lyrics, new[] { Lyrics });
                }
                else
                {
                    RemoveTag(TagType.Lyrics);
                }

                IsLyricsChanged = false;
            }

            //Set the conductor tag
            if (IsConductorChanged)
            {
                //_xiphComment.SetField(TagType.Conductor, new[] { Conductor });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Conductor);
                SetTagField(id3TagType, TagType.Conductor, new[] { Conductor });
                IsConductorChanged = false;
            }

            //Set the lyricist tag
            if (IsLyricistChanged)
            {
                //_xiphComment.SetField(TagType.Lyricist, new[] { Lyricist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Lyricist);
                SetTagField(id3TagType, TagType.Lyricist, new[] { Lyricist });
                IsLyricistChanged = false;
            }

            //Set the original lyricist tag
            if (IsOriginalLyricistChanged)
            {
                //_xiphComment.SetField(TagType.OriginalLyricist, new[] { OriginalLyricist });
                id3TagType = ConverFlacTypesToMp3Types(TagType.OriginalLyricist);
                SetTagField(id3TagType, TagType.OriginalLyricist, new[] { OriginalLyricist });
                IsOriginalLyricistChanged = false;
            }

            //Set the label tag
            if (IsLabelChanged)
            {
                //_xiphComment.SetField(TagType.Label, new[] { Label });
                id3TagType = ConverFlacTypesToMp3Types(TagType.Label);
                SetTagField(id3TagType, TagType.Label, new[] { Label });
                IsLabelChanged = false;
            }

            //Set the remixed by tag
            if (IsRemixedByChanged)
            {
                //_xiphComment.SetField(TagType.RemixedBy, new[] { RemixedBy });
                id3TagType = ConverFlacTypesToMp3Types(TagType.RemixedBy);
                SetTagField(id3TagType, TagType.RemixedBy, new[] { RemixedBy });
                IsRemixedByChanged = false;
            }

            //Set the radio station name tag
            if (IsRadioStationNameChanged)
            {
                //_xiphComment.SetField(TagType.RadioStationName, new[] { RadioStationName });
                id3TagType = ConverFlacTypesToMp3Types(TagType.RadioStationName);
                SetTagField(id3TagType, TagType.RadioStationName, new[] { RadioStationName });
                IsRadioStationNameChanged = false;
            }

            //Set the audio file url tag
            if (IsAudioFileUrlChanged)
            {
                //_xiphComment.SetField(TagType.AudioFileUrl, new[] { AudioFileUrl });
                id3TagType = ConverFlacTypesToMp3Types(TagType.AudioFileUrl);
                SetTagField(id3TagType, TagType.AudioFileUrl, new[] { AudioFileUrl });
                IsAudioFileUrlChanged = false;
            }

            //Set the author url tag
            if (IsAuthorUrlChanged)
            {
                //_xiphComment.SetField(TagType.AuthorUrl, new[] { AuthorUrl });
                id3TagType = ConverFlacTypesToMp3Types(TagType.AuthorUrl);
                SetTagField(id3TagType, TagType.AuthorUrl, new[] { AuthorUrl });
                IsAuthorUrlChanged = false;
            }

            //Set the audio source url tag
            if (IsAudioSourceUrlChanged)
            {
                //_xiphComment.SetField(TagType.AudioSourceUrl, new[] { AudioSourceUrl });
                id3TagType = ConverFlacTypesToMp3Types(TagType.AudioSourceUrl);
                SetTagField(id3TagType, TagType.AudioSourceUrl, new[] { AudioSourceUrl });
                IsAudioSourceUrlChanged = false;
            }

            //Set the radio station url tag
            if (IsRadioStationUrlChanged)
            {
                //_xiphComment.SetField(TagType.RadioStationUrl, new[] { RadioStationUrl });
                id3TagType = ConverFlacTypesToMp3Types(TagType.RadioStationUrl);
                SetTagField(id3TagType, TagType.RadioStationUrl, new[] { RadioStationUrl });
                IsRadioStationUrlChanged = false;
            }

            //Set the buy cd url tag
            if (IsBuyCdUrlChanged)
            {
                //_xiphComment.SetField(TagType.BuyCdUrl, new[] { BuyCdUrl });
                id3TagType = ConverFlacTypesToMp3Types(TagType.BuyCdUrl);
                SetTagField(id3TagType, TagType.BuyCdUrl, new[] { BuyCdUrl });
                IsBuyCdUrlChanged = false;
            }
        }

        #endregion

        #region Private Methods.

        private void ReadFrontCoverArt()
        {
            MemoryStream ms = null;

            ArtImage = null;

            ArtSize = 0;

            IPicture[] pic = _taglibfile.Tag.Pictures;

            foreach (IPicture picture in pic)
            {
                if (picture.Type == PictureType.FrontCover && picture.Data.Count > 0)
                {
                    try
                    {
                        ms = new MemoryStream(picture.Data.Data, 0, picture.Data.Data.Length);
                        ms.Seek(0, SeekOrigin.Begin);
                        ArtByteArray = picture.Data.Data;
                        ArtSize = _taglibfile.Tag.Pictures[0].Data.Data.Length;
                        ArtImage = Image.FromStream(ms, false, true);
                    }
                    catch (ArgumentException)
                    {
                        RemoveFrontCoverArt();
                    }
                }
            }

            if (ms != null)
            {
                ms.Close();
            }
        }

        private bool CreateMp3File(string path)
        {
            try
            {
                _audioFile = AudioFile.Create(path, false);

                if (_audioFile.FileType == AudioFileType.Mpeg)
                {
                    _mpeg = new Mpeg(path, true);
                    _descriptiveLameTagReader = new DescriptiveLameTagReader(path);
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private bool CreateTagLibFile(string path)
        {
            try
            {
                _taglibfile = File.Create(path, ReadStyle.Average);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private void ReadFileInfo()
        {
            _tagid3V2 = (TagLib.Id3v2.Tag)_taglibfile.GetTag(TagTypes.Id3v2);

            _tagid3V1 = (TagLib.Id3v1.Tag) _taglibfile.GetTag(TagTypes.Id3v1);

            var fileInfo = new FileInfo(FullPath);

            //Create a file path
            FilePath = string.Format("{0}{1}", Path.GetDirectoryName(FullPath), Path.DirectorySeparatorChar);

            //Read the file name
            FileName = Path.GetFileName(FullPath);

            //Read bitrate
            //BitRate = _taglibfile.Properties.AudioBitrate;

            //Read duration
            if (_taglibfile.Properties.Duration.Hours > 0)
            {
                Time = string.Format("{0:0#}:{1:0#}:{2:0#}", _taglibfile.Properties.Duration.Hours, _taglibfile.Properties.Duration.Minutes, _taglibfile.Properties.Duration.Seconds);
            }
            else
            {
                Time = string.Format("{0:0#}:{1:0#}", _taglibfile.Properties.Duration.Minutes, _taglibfile.Properties.Duration.Seconds);
            }

            TimeTicks = _taglibfile.Properties.Duration.Ticks;

            //Read the file size
            Size = fileInfo.Length;

            //Read the sample rate
            SampleRate = _taglibfile.Properties.AudioSampleRate.ToString(CultureInfo.InvariantCulture);
            
            //Read the bps
            BitsPerSample = "-";
            
            //Read bitrate
            if (_mpeg != null)
            {
                decimal bitrate = Math.Round(_mpeg.Bitrate, 0);

                if (_mpeg.IsVBR)
                {
                    BitRate = string.Format("{0} (VBR)", bitrate.ToString(CultureInfo.InvariantCulture));
                }
                else
                {
                    BitRate = string.Format("{0} (CBR)", bitrate.ToString(CultureInfo.InvariantCulture));
                }
            }
            else
            {
                decimal bitrate = Math.Round(_audioFile.Bitrate, 0);

                BitRate = bitrate.ToString(CultureInfo.InvariantCulture);
            }
            
            //Read channels
            Channels = _taglibfile.Properties.AudioChannels;

            //Read the encoder info
            if (_descriptiveLameTagReader != null)
            {
                Encoder = _descriptiveLameTagReader.LameTagInfoEncoder;
            }
        }

        private string ReadTagArrayValue(string[] array)
        {
            if (array.Length > 0)
            {
                return array[0];
            }
                
            return string.Empty;
        }

        private string GetStringFromByteArray(IEnumerable<byte> bytes)
        {
            var sb = new StringBuilder();

            foreach (var b in bytes)
            {
                if (b >= 34 && b <= 126)
                {
                    var c = (char)b;

                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        private byte[] GetByteArrayFromStringy(string text, bool addDelimiterFirst)
        {
            if (string.IsNullOrEmpty(text))
                return new byte[0];

            char[] charArray = text.ToCharArray();

            var byteArray = new byte[charArray.Length + 2];

            if (addDelimiterFirst)
            {
                byteArray[0] = 0;
                byteArray[1] = 0;

                for (int i = 2; i < charArray.Length + 2; i++)
                {
                    byteArray[i] = Convert.ToByte(charArray[i - 2]);
                }
            }
            else
            {
                int index = 0;

                for (int i = 0; i < charArray.Length; i++)
                {
                    byteArray[i] = Convert.ToByte(charArray[i]);

                    index = i;
                }

                byteArray[index + 1] = 0;
                byteArray[index + 2] = 0;
            }


            return byteArray;
        }

        private string ConverFlacTypesToMp3Types(string flactype)
        {
            switch (flactype)
            {
                case "ARTIST":
                    return "TPE1";
                case "ALBUM":
                    return "TALB";
                case "TITLE":
                    return "TIT2";
                case "DATE":
                    return "TYER";
                case "H2_RELEASE_YEAR":
                    return "TDRC";
                case "RELEASEYEAR":
                    return "TDRL";
                case "GENRE":
                    return "TCON";
                case "COMMENT":
                    return "COMM";
                case "H2_COMMENT":
                    return "TXXX";
                case "TRACKNUMBER":
                    return "TRCK";
                case "DISCNUMBER":
                    return "TPOS";
                case "LABELNO":
                    return "COMM";
                case "CATALOG NUMBER":
                    return "COMM";
                case "ISRC":
                    return "TSRC";
                case "H2_RELEASE_TYPE":
                    return "TXXX";
                case "ALBUMARTIST":
                    return "TPE2";
                case "H2_ALBUM_ARTIST":
                    return "TXXX";
                case "ALBUM ARTIST":
                    return "TPE2";
                case "COMPOSER":
                    return "TCOM";
                case "ORIGINALARTIST":
                    return "TOPE";
                case "COPYRIGHT":
                    return "TCOP";
                case "URL":
                    return "WXXX";
                case "ENCODEDBY":
                    return "TENC";
                case "MOOD":
                    return "TMOO";
                case "RATING":
                    return "POPM";
                case "QUALITY":
                    return "COMM";
                case "BPM":
                    return "TBPM";
                case "LYRICS":
                    return "USLT";
                case "LYRICIST":
                    return "TEXT";
                case "ORIGINALLYRICIST":
                    return "TOLY";
                case "RADIOSTATIONNAME":
                    return "TRSN";
                case "LABEL":
                    return "TPUB";
                case "CONDUCTOR":
                    return "TPE3";
                case "VERSION":
                    return "TPE4";
                case "AUDIOFILEURL":
                    return "WOAF";
                case "AUDIOSOURCEURL":
                    return "WOAS";
                case "AUTHORURL":
                    return "WOAR";
                case "BUYCDURL":
                    return "WCOM";
                case "RADIOSTATIONURL":
                    return "WORS";
                case "REMOVER":
                    return "REMOVER";
                default:
                    return string.Empty;
            }
        }

        public Frame GetTagFrame(string tagtype, string subtype)
        {
            if (tagtype == "TXXX" && subtype == "H2_RELEASE_TYPE")
            {
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "ReleaseType")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "TXXX" && subtype == "H2_COMMENT")
            {
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "Comment")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "TXXX" && subtype == "H2_ALBUM_ARTIST")
            {
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "AlbumArtist")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "COMM" && subtype == "CATALOG NUMBER")
            {
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "Catalog Number")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "COMM" && subtype == "LABELNO")
            {
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "LABELNO")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "COMM" && subtype == "MOOD")
            {
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "MusicMatch_Mood")
                    {
                        return frame;
                    }
                }
            }

            if (tagtype == "COMM" && subtype == "QUALITY")
            {
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "Songs-DB_Preference")
                    {
                        return frame;
                    }
                }
            }

            string ident = ConverFlacTypesToMp3Types(tagtype);

            if (!string.IsNullOrEmpty(ident) && ident.Length == 4)
            {
                List<Frame> list = _tagid3V2.GetFrames(ident).ToList();
                return list[0];
            }

            return null;
        }

        public string GetTagField(string tagtype, string subtype)
        {
            if (tagtype == "TXXX" && subtype == "H2_RELEASE_TYPE")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "ReleaseType")
                    {
                        tagField = ((UserTextInformationFrame)frame).Text[0];
                    }
                }

                return tagField;
            }

            if (tagtype == "TXXX" && subtype == "H2_COMMENT")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "Comment")
                    {
                        tagField = ((UserTextInformationFrame)frame).Text[0];
                    }
                }

                return tagField;
            }

            if (tagtype == "TXXX" && subtype == "H2_ALBUM_ARTIST")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "AlbumArtist")
                    {
                        tagField = ((UserTextInformationFrame)frame).Text[0];
                    }
                }

                return tagField;
            }

            if (tagtype == "COMM" && subtype == "CATALOG NUMBER")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "Catalog Number")
                    {
                        tagField = ((CommentsFrame)frame).Text;
                    }
                }

                return tagField;
            }

            if (tagtype == "COMM" && subtype == "LABELNO")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(CommentsFrame))
                    {
                        if (((CommentsFrame)frame).Description == "LABELNO")
                        {
                            tagField = ((CommentsFrame)frame).Text;
                        }
                    }
                }

                return tagField;
            }

            if (tagtype == "COMM" && subtype == "MOOD")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "MusicMatch_Mood")
                    {
                        tagField = ((CommentsFrame)frame).Text;
                    }
                }

                return tagField;
            }

            if (tagtype == "COMM" && subtype == "QUALITY")
            {
                string tagField = string.Empty;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((CommentsFrame)frame).Description == "Songs-DB_Preference")
                    {
                        tagField = ((CommentsFrame)frame).Text;
                    }
                }

                return tagField;
            }

            if (!string.IsNullOrEmpty(tagtype) && tagtype.Length == 4)
            {
                List<Frame> list = _tagid3V2.GetFrames(tagtype).ToList();

                if (list.Count > 0)
                    return list[0].ToString();
            }

            return string.Empty;

        }

        public void SetTagField(string tagtype, string subtype, string[] value)
        {
            if (tagtype == "TXXX" && subtype == "H2_RELEASE_TYPE")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "ReleaseType")
                    {
                        ((UserTextInformationFrame)frame).Text = value;
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UserTextInformationFrame("ReleaseType", StringType.UTF16);
                    frame.Text = value;
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "TXXX" && subtype == "H2_COMMENT")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "Comment")
                    {
                        ((UserTextInformationFrame)frame).Text = value;
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UserTextInformationFrame("Comment", StringType.UTF16);
                    frame.Text = value;
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "TXXX" && subtype == "H2_ALBUM_ARTIST")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("TXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (((UserTextInformationFrame)frame).Description == "AlbumArtist")
                    {
                        ((UserTextInformationFrame)frame).Text = value;
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UserTextInformationFrame("AlbumArtist", StringType.UTF16);
                    frame.Text = value;
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "COMM" && subtype == "CATALOG NUMBER")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(CommentsFrame))
                    {
                        if (((CommentsFrame)frame).Description == "Catalog Number")
                        {
                            ((CommentsFrame)frame).Text = value[0];
                            exist = true;
                        }
                    }
                }

                if (!exist)
                {
                    var frame = new CommentsFrame("Catalog Number", "ENG");
                    frame.Text = value[0];
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "COMM" && subtype == "LABELNO")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(CommentsFrame))
                    {
                        if (((CommentsFrame)frame).Description == "LABELNO")
                        {
                            ((CommentsFrame)frame).Text = value[0];
                            exist = true;
                        }
                    }
                }

                if (!exist)
                {
                    var frame = new CommentsFrame("LABELNO", "ENG");
                    frame.Text = value[0];
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "COMM" && subtype == "MOOD")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(CommentsFrame))
                    {
                        if (((CommentsFrame)frame).Description == "MusicMatch_Mood")
                        {
                            ((CommentsFrame)frame).Text = value[0];
                            exist = true;
                        }
                    }
                }

                if (!exist)
                {
                    var frame = new CommentsFrame("MusicMatch_Mood");
                    frame.Text = value[0];
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "COMM" && subtype == "QUALITY")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("COMM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(CommentsFrame))
                    {
                        if (((CommentsFrame)frame).Description == "Songs-DB_Preference")
                        {
                            ((CommentsFrame)frame).Text = value[0];
                            exist = true;
                        }
                    }
                }

                if (!exist)
                {
                    var frame = new CommentsFrame("Songs-DB_Preference");
                    frame.Text = value[0];
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "USLT" && subtype == "LYRICS")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("USLT");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnsynchronisedLyricsFrame))
                    {
                        if (((UnsynchronisedLyricsFrame)frame).Description == "Unsynchronized Lyrics")
                        {
                            ((UnsynchronisedLyricsFrame)frame).Text = value[0];
                            exist = true;
                        }
                        else
                        {
                            ((UnsynchronisedLyricsFrame)frame).TextEncoding = StringType.UTF16;
                            ((UnsynchronisedLyricsFrame)frame).Language = "ENG";
                            ((UnsynchronisedLyricsFrame)frame).Text = value[0];
                            exist = true;
                        }
                    }
                }

                if (!exist)
                {
                    var frame = new UnsynchronisedLyricsFrame("Unsynchronized Lyrics", "ENG", StringType.UTF16);
                    frame.Text = value[0];
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "POPM" && subtype == "RATING")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("POPM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(PopularimeterFrame))
                    {
                        byte b;
                        byte.TryParse(value[0], out b);

                        ((PopularimeterFrame)frame).User = "Default";
                        ((PopularimeterFrame)frame).Rating = b;
                        exist = true;
                    }
                }

                if (!exist)
                {
                    byte b;
                    byte.TryParse(value[0], out b);

                    var frame = new PopularimeterFrame("Default");
                    frame.Rating = b;
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WXXX" && subtype == "URL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WXXX");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], true);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WXXX");
                    frame.Data = GetByteArrayFromStringy(value[0], true);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WOAR" && subtype == "AUTHORURL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WOAR");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], false);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WOAR");
                    frame.Data = GetByteArrayFromStringy(value[0], false);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WOAF" && subtype == "AUDIOFILEURL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WOAF");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], false);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WOAF");
                    frame.Data = GetByteArrayFromStringy(value[0], false);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WCOM" && subtype == "BUYCDURL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WCOM");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], false);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WCOM");
                    frame.Data = GetByteArrayFromStringy(value[0], false);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WOAS" && subtype == "AUDIOSOURCEURL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WOAS");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], false);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WOAS");
                    frame.Data = GetByteArrayFromStringy(value[0], false);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype == "WORS" && subtype == "RADIOSTATIONURL")
            {
                bool exist = false;
                var frames = _tagid3V2.GetFrames("WORS");
                List<Frame> frameList = frames.ToList();

                foreach (var frame in frameList)
                {
                    if (frame.GetType() == typeof(UnknownFrame))
                    {
                        ((UnknownFrame)frame).Data = GetByteArrayFromStringy(value[0], false);
                        exist = true;
                    }
                }

                if (!exist)
                {
                    var frame = new UnknownFrame("WORS");
                    frame.Data = GetByteArrayFromStringy(value[0], false);
                    _tagid3V2.AddFrame(frame);
                }

                return;
            }

            if (tagtype != "COMM" && subtype != string.Empty)
            {
                _tagid3V2.SetTextFrame(tagtype, value);
            }
        }

        #endregion
    }
}
